﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DDD;
using Xunit;

namespace DokiDokiTest {
    public class TestObject3D {
        [Fact]
        public void Test_New1 () {
            var obj = (Object3D)new Node ();

            Assert.Equal (new float[] { 0, 0, 0 }, (float[])obj.Translation, new FloatComparer(0.0001f));
            Assert.Equal (new float[] { 1, 1, 1 }, (float[])obj.Scaling, new FloatComparer (0.0001f));
            Assert.Equal ((float[])Quaternion.Identity, (float[])obj.Orientation);
            Assert.Equal ((float[])Matrix4x4.Identity, (float[])obj.Matrix);
        }

        [Fact]
        public void Test_Translate () {
            var obj = (Object3D)new Node ();
            obj.Translate (1, 2, 3);
            Assert.Equal (1, obj.Translation[0]);
            Assert.Equal (2, obj.Translation[1]);
            Assert.Equal (3, obj.Translation[2]);

            obj.Translate (4, 5, 6);
            Assert.Equal (5, obj.Translation[0]);
            Assert.Equal (7, obj.Translation[1]);
            Assert.Equal (9, obj.Translation[2]);
        }

        [Fact]
        public void Test_SetTranslation () {
            var obj = (Object3D)new Node ();
            
            obj.SetTranslation (1, 2, 3);
            Assert.Equal (1, obj.Translation[0]);
            Assert.Equal (2, obj.Translation[1]);
            Assert.Equal (3, obj.Translation[2]);

            obj.SetTranslation (4, 5, 6);
            Assert.Equal (4, obj.Translation[0]);
            Assert.Equal (5, obj.Translation[1]);
            Assert.Equal (6, obj.Translation[2]);
        }

        [Fact]
        public void Test_Rotate1 () {
            var obj = (Object3D)new Node ();

            var rotZ45 = new Quaternion (45, 0, 0, 1);
            var rotZ90 = new Quaternion (90, 0, 0, 1);

            obj.Rotate (new Quaternion (45, 0, 0, 1));
            Assert.Equal ((float[])rotZ45, (float[])obj.Orientation, new FloatComparer(0.0001f));

            obj.Rotate (new Quaternion (45, 0, 0, 1));
            Assert.Equal ((float[])rotZ90, (float[])obj.Orientation, new FloatComparer (0.001f));
        }

        [Fact]
        public void Test_Rotate2 () {
            var obj = (Object3D)new Node ();

            var rotZ45 = new Quaternion (45, 0, 0, 1);
            var rotZ90 = new Quaternion (90, 0, 0, 1);

            obj.Rotate (45, 0, 0, 1);
            Assert.Equal ((float[])rotZ45, (float[])obj.Orientation, new FloatComparer (0.0001f));

            obj.Rotate (45, 0, 0, 1);
            Assert.Equal ((float[])rotZ90, (float[])obj.Orientation, new FloatComparer (0.0001f));
        }

        [Fact]
        public void Test_SetOrientation1 () {
            var obj = (Object3D)new Node ();

            var rotZ45 = new Quaternion (45, 0, 0, 1);
            var rotZ90 = new Quaternion (90, 0, 0, 1);

            obj.SetOrientation (new Quaternion (45, 0, 0, 1));
            Assert.Equal ((float[])rotZ45, (float[])obj.Orientation, new FloatComparer (0.0001f));

            obj.SetOrientation (new Quaternion (90, 0, 0, 1));
            Assert.Equal ((float[])rotZ90, (float[])obj.Orientation, new FloatComparer (0.0001f));
        }

        [Fact]
        public void Test_SetOrientation2 (){
            var obj = (Object3D)new Node ();

            var rotZ45 = new Quaternion (45, 0, 0, 1);
            var rotZ90 = new Quaternion (90, 0, 0, 1);

            obj.SetOrientation (45, 0, 0, 1);
            Assert.Equal ((float[])rotZ45, (float[])obj.Orientation, new FloatComparer (0.0001f));

            obj.SetOrientation (90, 0, 0, 1);
            Assert.Equal ((float[])rotZ90, (float[])obj.Orientation, new FloatComparer (0.0001f));
        }

        [Fact]
        public void Test_SetMatrix () {
            var obj = (Object3D)new Node ();
            var m = new Matrix4x4 (1,2,3,4,
                                   5,6,7,8,
                                   9,10,11,12,
                                   13,14,15,16);
            obj.SetMatrix (m);

            Assert.Equal ((float[])m, (float[])obj.Matrix);
        }

        [Fact]
        public void Test_LookAt1 () {
            var obj = (Object3D)new Node ();

            obj.LookAt (0, 0, 10,
                        0, 0, 0,
                        0, 1, 0);

            var expectedT = new float[] { 0, 0, 10 };
            var expectedR = new float[] { 0, 0, 0, 1 };
            Assert.Equal (expectedT, (float[])obj.Translation, new FloatComparer(0.0001f));
            Assert.Equal (expectedR, (float[])obj.Orientation, new FloatComparer(0.0001f));

        }

        [Fact]
        public void Test_LookAt2 () {
            var obj = (Object3D)new Node ();

            obj.LookAt (10, 0, 0,
                        0, 0, 0,
                        0, 1, 0);
            var expectedT = new float[] { 10, 0, 0 };
            var expectedR = new float[] { 0, 0.7071068f, 0, 0.7071068f };
            Assert.Equal (expectedT, (float[])obj.Translation, new FloatComparer (0.0001f));
            Assert.Equal (expectedR, (float[])obj.Orientation, new FloatComparer (0.0001f));
        }

        [Fact]
        public void Test_Align () {
            // not implemented
        }

     }
}
